import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.ArrayList;
import java.util.Scanner;

//当前代码无法给多个客户端提供服务端
public class TCPEchoServer {
    private ServerSocket serverSocket = null;

    public TCPEchoServer(int port) throws IOException {
        serverSocket = new ServerSocket(port);
    }

    public void start() throws IOException {
        System.out.println("服务器启动!");
        while (true){
            Socket clientSocket = serverSocket.accept();//客户端申请连接,服务器一启动就会执行
            //如果没有客户端连接,就会阻塞,直到有客户端连接
            //如果采用多线程,就不能用 try 来关闭 clientSocket
            //否则就会使 clientSocket 被立即关闭,此时 ProcessConnection 还没使用
            Thread t = new Thread(()->{
                try {
                    processConnection(clientSocket);
                } catch (IOException e) {
                    throw new RuntimeException(e);
                }
            });
            t.start();
        }
    }
    //通过这个方法来处理一个连接
    public void processConnection(Socket clientSocket) throws IOException {
        //1.打印日志 告知当前有客户端连接上
        //要用到 % 来打印的都只能用 printf ,不能使用 print 或者 println
        System.out.printf("[%s:%d] 客户端上线!\n",clientSocket.getInetAddress(),clientSocket.getPort());

        //2.从 Socket 中获取到流对象,来进一步进行后续操作
        //使用完可以顺便关闭
        try (InputStream inputStream = clientSocket.getInputStream();
                OutputStream outputStream = clientSocket.getOutputStream()){

            //3.循环 针对每个连接,客户端可能会发来多个请求,服务器也就需要返回多个响应
            Scanner scanner = new Scanner(inputStream);
            while (true){
                //3.1 读取请求并解析
                if(!scanner.hasNext()){
                    //这里就会阻塞
                    //看是否能读取到后续内容
                    //读取不到 --> TCP 连接断开
                    System.out.printf("[%s:%d] 客户端下线!\n",clientSocket.getInetAddress(),clientSocket.getPort());
                    break;
                }
                String request = scanner.next();//读取到空白符就停止
                //如果使用的是 read 方法来读,读出来的就是 byte[] 还需要转成String
                //如果使用 Scanner ,直接俄读出来的就是 String

                //3.2 根据请求计算响应
                String response = process(request);

                //3.3 把响应写回给客户端
                outputStream.write(response.getBytes());
            }
        } catch (IOException e) {
            throw new RuntimeException(e);
        }finally {
            clientSocket.close();
        }
    }

    public  String process(String request){
        //根据请求计算响应
        //由于是回显服务器 直接把请求最为响应返回回去
        return request + "\n";
        //加上换行 使客户端在读取响应的是由,有明显的分隔符
    }
    public static void main(String[] args) throws IOException {
        TCPEchoServer server = new TCPEchoServer(9090);
        server.start();
    }
    
}
